package eu.best.sercheng.model.dao;

import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.criterion.Restrictions;
import org.hibernate.tool.hbm2ddl.SchemaExport;

import eu.best.sercheng.model.ResultQuery;
import eu.best.sercheng.model.entity.DomainRules;
import eu.best.sercheng.model.entity.Keyword;
import eu.best.sercheng.model.entity.RelationKeyPage;
import eu.best.sercheng.model.entity.RelationKeyPagePK;
import eu.best.sercheng.model.entity.Rule;
import eu.best.sercheng.model.entity.VisitedPage;

public class MainDaoImpl implements MainDao {
	private static SessionFactory factory;
	
	private static Logger logger = Logger.getLogger(MainDaoImpl.class.getName());
	
	static {
		AnnotationConfiguration config = new AnnotationConfiguration();
		config.addAnnotatedClass(Keyword.class);
		config.addAnnotatedClass(VisitedPage.class);
		config.addAnnotatedClass(RelationKeyPage.class);
		config.addAnnotatedClass(DomainRules.class);
		config.addAnnotatedClass(Rule.class);
		config.configure("hibernate.cfg.xml");
		new SchemaExport(config).create(true, true);
		factory = config.buildSessionFactory();
	}
	
	
	@Override
	public void putWordsToUrl(String URL, List<String> keywords) {
		URL = URL.toLowerCase().trim();
		
		Session session = getSession();
		session.beginTransaction();
		Query query = session.createQuery("SELECT u FROM VisitedPage u WHERE u.URL = :URL");
		query.setParameter("URL", URL);
		VisitedPage visitedPage = (VisitedPage) query.uniqueResult();
		
		if(visitedPage == null){
			visitedPage = new VisitedPage();
			visitedPage.setURL(URL);
			session.saveOrUpdate(visitedPage);
		}
		session.getTransaction().commit();

		for(String keyword:keywords){
			keyword = keyword.toLowerCase().trim();
			try{
				session = getSession();
				session.beginTransaction();
				query = null;
				query = session.createQuery("SELECT k FROM Keyword k WHERE k.keyword = :key");
				query.setParameter("key", keyword);
				Keyword savedKey = (Keyword) query.uniqueResult();
				
				if(savedKey == null){
					savedKey = new Keyword();
					savedKey.setKeyword(keyword);
					session.saveOrUpdate(savedKey);
				}
				
				RelationKeyPagePK pk = new RelationKeyPagePK(savedKey, visitedPage);
				query = null;
				query = session.createQuery("SELECT r FROM RelationKeyPage r WHERE r.pk = :pk");
				query.setParameter("pk", pk);
				RelationKeyPage relationKeyPage = (RelationKeyPage) query.uniqueResult();
				if(relationKeyPage == null){
					relationKeyPage = new RelationKeyPage(pk);
					savedKey.getRelatedKeyPages().add(relationKeyPage);
					visitedPage.getRelatedKeyPages().add(relationKeyPage);
				}else{
					relationKeyPage.setOccurence(relationKeyPage.getOccurence()+1);
				}
				try{
					session.saveOrUpdate(savedKey);
					session.saveOrUpdate(relationKeyPage);
				}catch(Exception e){
					e.printStackTrace();
				}
				session.getTransaction().commit();
			}catch (Exception e) {
				logger.error("error during saving"+keyword,e);
			}
		}

	}

	@Override
	public List<VisitedPage> getURLsForKeyword(String keyword) {
		Session session = getSession();
		
		Criteria createCriteria = session.createCriteria(Keyword.class);
		createCriteria.add(Restrictions.eq("keyword", keyword));
		Keyword key = (Keyword) createCriteria.uniqueResult();
		
		LinkedList<VisitedPage> results = new LinkedList<VisitedPage>();
		if(key==null){
			return results;
		}
		for (RelationKeyPage relationKeyPage : key.getRelatedKeyPages()) {
			results.add(relationKeyPage.getPk().getVisitedPage());
		}

		return results;
	}

	public List<ResultQuery> getResultsForKeyword(String keyword){
		keyword = keyword.toLowerCase().trim();
		
		Session session = getSession();
		Criteria createCriteria = session.createCriteria(Keyword.class);
		createCriteria.add(Restrictions.eq("keyword", keyword));
		Keyword key = (Keyword) createCriteria.uniqueResult();
		
		LinkedList<ResultQuery> results = new LinkedList<ResultQuery>();
		if(key==null){
			return results;
		}
		
		for (RelationKeyPage relationKeyPage : key.getRelatedKeyPages()) {
			ResultQuery resultQuery = new ResultQuery();
			resultQuery.setURL(relationKeyPage.getPk().getVisitedPage().getURL());
			resultQuery.setQuantity(relationKeyPage.getOccurence());
			results.add(resultQuery);
		}
		return results;
	}
	
	@Override
	public DomainRules getRulesForDomain(String domain) {
		Session session = getSession();
//		session.beginTransaction();
		return (DomainRules)session.load(DomainRules.class, domain);
	}

	@Override
	public void persistDomainRules(DomainRules domainRules) {
		Session session = getSession();
		session.beginTransaction();
		session.saveOrUpdate(domainRules);
		session.getTransaction().commit();
	}

	public Session getSession(){
		return factory.openSession();
	}
	
	
	
}
